test

3.8 JRockit中的内存管理

本节将对JRockit垃圾回收相关的命令行参数进行简单介绍,更多详细内容参见第5章

3.8.1 基本参数

本节将对与JRockit内存管理相关的基本命令行参数做介绍。

3.8.1.1 打印垃圾回收日志

运行JRockit时,附加参数-Xverbose:gc会打印出很多JVM内存管理相关的信息,其中包含了垃圾回收的发生地点(新生代或老年代),垃圾回收策略的变更,以及执行垃圾回收所消耗哦时间。

除了使用JRockit Mission Control外,参数-Xverbose:gc(或者-Xverbose:memory)也可算是学习垃圾回收器具体行为的一种工具。

下面是使用-Xverbose:gc参数运行示例应用程序时打印的日志:

hastur:material marcus$ java –Xverbose:gc GarbageDemo
[INFO ][memory ] GC mode: Garbage collection optimized for throughput, strategy: Generational Parallel Mark & Sweep.
[INFO ][memory ] Heap size: 65536KB, maximal heap size: 382140KB, nursery size: 32768KB.
[INFO ][memory ] [YC#1] 1.028-1.077: YC 33232KB->16133KB (65536KB), 0.049 s, sum of pauses 48.474 ms, longest pause 48.474 ms.
[INFO ][memory ] [YC#2] 1.195-1.272: YC 41091KB->34565KB (65536KB), 0.077 s, sum of pauses 76.850 ms, longest pause 76.850 ms.
[INFO ][memory ] [YC#3] 1.857-1.902: YC 59587KB->65536KB (65536KB), 0.045 s, sum of pauses 45.122 ms, longest pause 45.122 ms.
[INFO ][memory ] [OC#1] 1.902-1.912: OC 65536KB->15561KB (78644KB), 0.010 s, sum of pauses 9.078 ms, longest pause 9.078 ms.
[INFO ][memory ] [YC#4] 2.073-2.117: YC 48711KB->39530KB (78644KB), 0.044 s, sum of pauses 44.435 ms, longest pause 44.435 ms.

一般情况下爱,日志中会包含垃圾回收策略变更消息,堆容量调整信息,以及垃圾回收的执行时间和执行时长。

其中,OCYC分别表示老年代垃圾回收(Old Collection)新生代垃圾回收(Nursery Collection),后跟垃圾回收操作的id编号,起始值为1。

再之后,是本次垃圾回收的起始和截止时间,其具体指是从JVM启动之后的时间偏移,单位为秒。

接下来是,垃圾回收前后,相关区域的内存占用情况,分别是 回收前 回收后总容量。在此之后是对该区域进行垃圾回收所消耗的时间,

最后,是本次垃圾回收暂时时间信息,以及在本次垃圾回收中最长单次暂停时间。通过上面的示例可以推断出,垃圾回收是完全STW式的,即并行垃圾回收,其执行过程只有一个长暂停。

正如之前章节介绍的,垃圾回收周期中实际上包含了几个阶段,如果想要获取更多详细信息,请使用-Xverbose:gcpause参数。此外,在JRockit Mission Control中可以以图形化的方式查看垃圾回收的具体细节,以及更多应用程序相关的信息。

3.8.1.2 设置堆的初始值和最大值

参数-Xmx-Xms是所有JVM通用的标准参数,分别用于指定堆的最大值和初始值。如果没有设置,则堆的大小可能会在应用程序运行过程中,依据运行时反馈信息增大或缩小。以下面的配置为例:

java –Xms1024M –Xmx2048M <application>

上面的配置将对的初始值设置为为1GB,最大值为2GB,如果应用程序所使用的内存超过2GB,则JVM会抛出OutOfMemoryError错误。

3.8.1.3 设置垃圾回收器的执行目标

除非你是高端用户,否则最好使用-XgcPrio参数来设置垃圾回收器的优化目标,因为垃圾回收器会根据优化目标和运行时反馈信息来指定垃圾回收策略。

  • –XgcPrio:throughput: 主要针对吞吐量进行优化,不关心响应时间
  • –XgcPrio:pausetime: 主要针对低延迟进行优化
  • -XgcPrio:deterministic: 该参数会启用JRockit Real Time,尽量满足对指定响应时间的要求

如果以最大暂停时间为优化目标的话,可以设置参数-XpauseTarget,根据堆中存活对象的数量和系统配置,JRockit会尽量满足这个期望的暂停时间要求,但无法确定会满足,需要针对具体应用程序做大量测试来确认。

下面的配置启用了Jrockit Real Time,并设置了暂停时间的上限:

java –XgcPrio:deterministic –XpauseTarget:5ms <application>

3.8.1.4 指定垃圾回收策略

要想进一步控制垃圾回收的行为,可以使用-Xgc相关的参数做详细的配置。该系列参数用于指定垃圾回收策略,避免在应用程序运行过程中发生改变,相比于使用-XgcPrio系列参数,-Xgc系列参数可以更细致的控制垃圾回收策略。再强调一次,并发并行非别用于描述低延迟垃圾回收和高吞吐垃圾回收。-Xgc系列参数如下,其中,generationalsingle generational的区别在于启用了新生代:

  • -Xgc:singlecon: single generational concurrent,不分代的并发垃圾回收
  • -Xgc:gencon: generational concurrent,分代式并发垃圾回收
  • -Xgc:singlepar: single generational parallel,不分代的并行垃圾回收
  • -Xgc:genpar: generational parallel,分代式并行垃圾回收

3.8.2 压缩引用

正如前面章节介绍的,当堆的最大值小于64GB时,JRockit默认会使用某种形式的引用压缩,但也可以通过命令行参数-XXcompressedRefs来显式指定,该参数有两个可选参数,分别是是否启用引用压缩和所支持的堆的大小。

下面的配置禁用了引用压缩,所以JRockit会使用使用原始本地指针来表示对象地址:

java –XXcompressedRefs:enable=false <application>

下面的配置启用了引用压缩,并指定所支持的堆的大小是64GB:

java –XXcompressedRefs:enable=true,size=64GB <application>

译者注,引用压缩对不同大小堆的支持参见这篇文章,https://blogs.oracle.com/jrockit/entry/understanding_compressed_refer

3.8.3 高级选项

需要注意的是,花大力气鼓捣JVM参数并不一定会使应用程序性能有多么大的提升,而且可能会干扰JVM的正常运行。

如果排查到应用程序的性能瓶颈在于内存管理,建议使用JRockit Mission Control来探查具体原因。本书后面的章节会详细介绍如果记录、分析JRockit的运行信息。强烈建议在动手修改JVM的非标准参数之前,尽可能多的手机应用程序的运行信息。

垃圾回收器每一个角落,从TLB到堆的整理策略,几乎都可以通过命令行参数加以控制。

第5章会对一些高级内存管理参数做介绍,更多与内存管理相关的详细信息参加JRockit相关文档。